package com.nulldev.util.graphics.renderIt.ginterfaces_simulators.j2me;

import java.awt.Component;
import java.awt.Graphics;
import java.util.concurrent.atomic.AtomicReference;

import javax.swing.JComponent;
import javax.swing.JFrame;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.data.Images.ColorUtil;
import com.nulldev.util.graphics.renderIt.api.renderItConstants;
import com.nulldev.util.graphics.renderIt.api.renderItGraphicsInterface;
import com.nulldev.util.graphics.renderIt.api.core.IRenderCallback;
import com.nulldev.util.graphics.renderIt.api.core.IRenderCallbackMetadata;
import com.nulldev.util.graphics.renderIt.api.core.IRenderCanvas;
import com.nulldev.util.graphics.renderIt.api.core.RITFont;
import com.nulldev.util.graphics.renderIt.api.envcaps.renderItCanvasOperations;
import com.nulldev.util.graphics.renderIt.api.envcaps.renderItOperations;
import com.nulldev.util.graphics.renderIt.api.utils.GLSimpleTextDraw;
import com.nulldev.util.graphics.renderIt.renderer.global.rColors;
import com.nulldev.util.graphics.renderIt.renderer.swing.smoothCanvas.CanvasFrameCallback;
import com.nulldev.util.graphics.renderIt.renderer.swing.smoothCanvas.RenderMethod;
import com.nulldev.util.graphics.renderIt.renderer.swing.smoothCanvas.SmoothCanvas;
import com.nulldev.util.graphics.renderIt.renderer.swing.smoothCanvas.SyncMethod;
import com.nulldev.util.manage.legacy.FPSCounter;

public class VirtualJ2MERenderPane extends SmoothCanvas implements CanvasFrameCallback, IRenderCanvas {
	private static final long serialVersionUID = 5405315392986849340L;

	private static final renderItCanvasOperations[] CANVAS_OPS =
		{ renderItCanvasOperations.RIT_canvas_visibility, renderItCanvasOperations.RIT_canvas_bounds,

				renderItCanvasOperations.RIT_output_awt_component, renderItCanvasOperations.RIT_output_swing_component,
				renderItCanvasOperations.RIT_canvas_callback, };
	private final VirtualJ2MERenderInterface sri;
	private final AtomicReference<IRenderCallback> renderCallback = new AtomicReference<IRenderCallback>();
	private final JFrame jfr;

	public VirtualJ2MERenderPane() {
		this(null);
	}

	public VirtualJ2MERenderPane(final JFrame jfr) {
		super(RenderMethod.REPAINT_WITHIN_SYNC, SyncMethod.NO_SYNC);
		this.sri = new VirtualJ2MERenderInterface(getGraphics(), this, jfr);
		this.jfr = jfr;
		super.setRenderCallback(this);
	}

	@Override
	public void onFrame(Graphics g) {
		this.sri.updateGraphics(g);
		if (this.renderCallback.get() != null)
			this.renderCallback.get().onRender(this.sri, IRenderCallbackMetadata.DEFAULT);
	}

	public boolean hasRenderCallback() {
		return this.renderCallback.get() != null;
	}

	public void setRenderCallback(final IRenderCallback callback) {
		this.renderCallback.lazySet(callback);
	}

	public static void main(String[] args) {
		final JFrame jfr = new JFrame("(!!! VIRTUAL !!!) J2MERenderPane demo");
		jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		final VirtualJ2MERenderPane swr = new VirtualJ2MERenderPane(jfr);
		jfr.add(swr);
		jfr.setBounds(50, 50, 400, 400);
		jfr.setVisible(true);
		swr.start();
		swr.setRenderCallback(new IRenderCallback() {

			private final FPSCounter fpsc = new FPSCounter().startNow();
			private RITFont f;

			@Override
			public void onRender(final renderItGraphicsInterface iface, final IRenderCallbackMetadata metadata) {
				if (!iface.text_isAAPresent())
					iface.text_setAAPresence(true);
				if (f == null)
					f = iface.font_create("Roboto", 16f, RITFont.RIT_FONT_VARIANT_BOLD);
				iface.setColor(ColorUtil.rainbow(200, 1.0f).getRGB());
				iface.bd_fillRect(0, 0, iface.viewport_getWidth(), iface.viewport_getHeight());
				fpsc.callFPS();
				iface.setColor(rColors.white);
				GLSimpleTextDraw.drawString(iface, "FPS " + fpsc.getFPS(), 2, 5);
				iface.text_shadowedString("FPS (average): " + fpsc.getAVGFPS(), 5, 15, f);
			}
		});
		swr.start();
		JVM.println("renderIt: " + swr.sri.rit_version());
		JVM.println("Supported extensions: ");
		ArrayUtils.printLln(swr.sri.supportedOperations());
		JVM.println("Invoking `nullutil_swing_center()` from RIT_nullutil_swing_api.");
		swr.sri.nullutil_swing_center();
		JVM.println("Invoking `nullutil_swing_getRefreshRate()` from RIT_nullutil_swing_api.");
		JVM.println("Refresh Rate: " + swr.sri.nullutil_swing_getRefreshRate() + " Hz.");
		JVM.println("Invoking `nullutil_swing_isUsingHWAccel()` from RIT_nullutil_swing_api.");
		JVM.println("HW Accel: " + swr.sri.nullutil_swing_isUsingHWAccel());
		if (swr.sri.supportsOperations(renderItOperations.RIT_font_file_formats)) {
			JVM.println("Checking for supported font formats: (using RIT_font_file_formats)");
			JVM.println("TTF Support: " + swr.sri.supportsFontFileFormat(renderItConstants.RIT_FONT_FORMAT_TTF));
			JVM.println("OTF Support: " + swr.sri.supportsFontFileFormat(renderItConstants.RIT_FONT_FORMAT_OTF));
			JVM.println("BITMAP Support: " + swr.sri.supportsFontFileFormat(renderItConstants.RIT_FONT_FORMAT_BITMAP));
		}
		if (swr.sri.supportsOperations(renderItOperations.NITROUS_accel_info)) {
			JVM.println("Invoking nitrous_getBackend: " + swr.sri.nitrous_getBackend());
		}
	}

	public int getViewportH() {
		return this.getHeight();
	}

	@Override
	public renderItCanvasOperations[] supportedOperations() {
		return CANVAS_OPS;
	}

	/* RIT_canvas_visibility */

	@Override
	public boolean canvas_isVisible() {
		if (this.jfr != null)
			return this.jfr.isVisible();
		return super.isVisible();
	}

	@Override
	public void canvas_setVisible(final boolean visible) {
		if (this.jfr != null) {
			this.jfr.setVisible(visible);
		} else {
			super.setVisible(visible);
		}
	}

	/* RIT_output_awt_component */

	public Component asAWTComponent() {
		return this;
	}

	/* RIT_output_swing_component */

	@Override
	public JComponent asSwingComponent() {
		return this;
	}

	/* RIT_canvas_bounds */

	@Override
	public int canvas_getWidth() {
		return super.getWidth();
	}

	@Override
	public int canvas_getHeight() {
		return super.getHeight();
	}

	@Override
	public void canvas_setWidth(final int width) {
		this.unsupported(renderItCanvasOperations.RIT_canvas_bounds);
	}

	@Override
	public void canvas_setHeight(final int height) {
		this.unsupported(renderItCanvasOperations.RIT_canvas_bounds);
	}
}
